home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / tde31.zip / TDECFG.C < prev    next >
C/C++ Source or Header  |  1993-08-29  |  28KB  |  887 lines

  1. /*
  2.  * A configuration utility was written to customize the tde executable file.
  3.  * You only need one file to run tde - the executable.  No configuration files
  4.  * to worry about.
  5.  *
  6.  * With this version, there is no need to figure the offsets each time
  7.  * tde.exe is modified.  The original program to find the offsets was written
  8.  * by Jim Lee, jlee@ece.orst.edu.  Simple pattern matching machines are used
  9.  * to find the offsets.  On one pass thru tde.exe, the machines will quickly
  10.  * find all signatures.
  11.  *
  12.  * ------------------------------------------------------------------------
  13.  * Jim Lee, jlee@ece.orst.edu, sent working code for finding the offsets of
  14.  * of various data structures in tde.exe.  Hoping to improve on the brute
  15.  * force method, I tried using a more complicated algorithm.  Needless to
  16.  * say and standard operating procedure, I did not correctly implement
  17.  * the more complicated algorithm.  For example,
  18.  *
  19.  *     my implementation would not find  "$  help"  in the string "$$  help"
  20.  *
  21.  * All bugs in Jim Lee's working code were introduced by me, Frank.
  22.  *
  23.  * Jimmy Thompson, jimmy_t@verifone.com, found the error and provided
  24.  * working code for the Knuth-Morris-Pratt algorithm.  Jimmy, thank you
  25.  * for the error report and the solution.
  26.  *
  27.  * That's what I get for acting like I'm so smart.  Not only did I
  28.  * incorrectly implement the Aho-Corasick algorithm, but I should have
  29.  * used the Knuth-Morris-Pratt algorithm.
  30.  *
  31.  *                   Frank Davis, August, 29, 1993, TDE 3.1
  32.  * ------------------------------------------------------------------------
  33.  *
  34.  * See:
  35.  *
  36.  *   Donald Ervin Knuth, James H. Morris, Jr., and Vaughan R. Pratt,
  37.  *     "Fast Pattern Matching in Strings."  _SIAM Journal on Computing_
  38.  *     6 (No. 2): 323-350, 1977.
  39.  *
  40.  *   Robert Sedgewick, _Algorithms in C_, Addison-Wesley, Reading, Mass.,
  41.  *     1990, Chapter 19, "String Searching", pp. 277-292, ISBN 0-201-51425-7
  42.  *
  43.  *
  44.  *                        Knuth-Morris-Pratt in TDE
  45.  *
  46.  * To be safe and sure, the KMP algorithm is pretty much based on the
  47.  * description given in _SIAM J on Comp_.  Hints for KMP in C are from
  48.  * Dr. Sedgewick's book.  Actually, on average, finding a *text* string with
  49.  * KMP is not that much faster, if any, than a brute force search.  However,
  50.  * using KMP for finding several strings at once is probably faster than
  51.  * a brute force implementation.  Anyway, I think I got the implementation
  52.  * right, this time...
  53.  *
  54.  *
  55.  * Program name:  tdecfg
  56.  * Author:        Frank Davis
  57.  * Date:          October 5, 1991
  58.  * Date:          June 5, 1993
  59.  *
  60.  * This program is released into the public domain.  You may distribute
  61.  * it freely, Frank Davis.
  62.  */
  63.  
  64.  
  65. #include <bios.h>
  66. #include <dos.h>
  67. #include <io.h>
  68. #include <malloc.h>
  69. #include <stdlib.h>
  70. #include <stdio.h>
  71. #include <string.h>
  72.  
  73. #include "tdecfg.h"
  74.  
  75.  
  76. struct vcfg cfg;                /* video stuff */
  77. FILE *tde_exe;                  /* FILE pointer to tde.exe */
  78.  
  79. long sort_offset;
  80. long mode_offset;
  81. long color_offset;
  82. long macro_offset;
  83. long keys_offset;
  84. long two_key_offset;
  85. long help_offset;
  86.  
  87. struct screen cfg_choice[] = {
  88.    {5,25,"1.  Change colors" },
  89.    {7,25,"2.  Redefine keys" },
  90.    {9,25,"3.  Install new help screen" },
  91.   {11,25,"4.  Set default modes" },
  92.   {13,25,"5.  Install permanent macro file" },
  93.   {15,25,"6.  Read in a configuration file" },
  94.   {17,25,"7.  Exit" },
  95.  {20,20,"Please enter choice: " },
  96.   {0,0,NULL}
  97. };
  98.  
  99.  
  100. char *greatest_composer_ever = "W. A. Mozart, 1756-1791";
  101.  
  102.  
  103. /*
  104.  * Name:    main
  105.  * Date:    October 5, 1991
  106.  * Notes:   Strategy is fairly straight forward -  1) initialize all the
  107.  *          variables  2) show the user a color sample  3) make the changes
  108.  *          permanent if desired.
  109.  */
  110. void main( int argc, char *argv[] )
  111. {
  112. int  rc;
  113. int  c;
  114. char fname[82];
  115. char *buff;
  116.  
  117.    /*
  118.     * lets get a 8k buffer for our pattern matching machines.
  119.     */
  120.    if ((buff = malloc( 8200 )) == NULL) {
  121.       puts( "\nNot enough memory." );
  122.       exit( 1 );
  123.    }
  124.  
  125.    puts( "\nEnter tde executable file name (<Enter> = \"tde.exe\")  :" );
  126.    gets( fname );
  127.  
  128.    if (strlen(fname) == 0)
  129.       strcpy( fname, "tde.exe" );
  130.  
  131.    if ((rc = access( fname, EXIST )) != 0) {
  132.       puts( "\nFile not found." );
  133.       exit( 1 );
  134.    } else if ((tde_exe = fopen( fname, "r+b" )) == NULL ) {
  135.       puts( "\nCannot open executable file." );
  136.       exit( 2 );
  137.    }
  138.    if ((rc = find_offsets( buff )) == ERROR)
  139.       puts( "\nFatal error finding offsets.\n" );
  140.    free( buff );
  141.    if (rc == ERROR)
  142.       exit( 3 );
  143.  
  144.    video_config( );
  145.    cls( );
  146.    show_box( 0, 0, cfg_choice, NORMAL );
  147.    for (rc=0; rc != 1;) {
  148.       xygoto( 42, 20 );
  149.       c = getkey( );
  150.       while (c != '1' && c != '2' && c != '3' && c != '4' && c != '5' &&
  151.              c != '6' && c != '7')
  152.          c = getkey( );
  153.       switch (c) {
  154.          case '1' :
  155.             tdecolor( );
  156.             show_box( 0, 0, cfg_choice, NORMAL );
  157.             break;
  158.          case '2' :
  159.             tdekeys( );
  160.             show_box( 0, 0, cfg_choice, NORMAL );
  161.             break;
  162.          case '3' :
  163.             tdehelp( );
  164.             show_box( 0, 0, cfg_choice, NORMAL );
  165.             break;
  166.          case '4' :
  167.             tdemodes( );
  168.             show_box( 0, 0, cfg_choice, NORMAL );
  169.             break;
  170.          case '5' :
  171.             tdemacro( );
  172.             show_box( 0, 0, cfg_choice, NORMAL );
  173.             break;
  174.          case '6' :
  175.             tdecfgfile( );
  176.             show_box( 0, 0, cfg_choice, NORMAL );
  177.             break;
  178.          case '7' :
  179.             rc = 1;
  180.             break;
  181.       }
  182.    }
  183.    fcloseall( );
  184.    puts( " " );
  185.    puts( " " );
  186. }
  187.  
  188.  
  189. /***********************  original comments  *************************/
  190. /*
  191. ** OFFSETS.C    -       Automatically scan tde.exe for config offsets
  192. **
  193. ** Author:  Jim Lee (jlee@ece.orst.edu)
  194. **   Date:  5/12/93
  195. ** Status:  Released to the public domain
  196. **
  197. **      This little utility takes the drudgery out of updating tdecfg.h
  198. **      every time you re-compile tde.exe.  Just remove the hard-coded
  199. **      offsets in tdecfg.h and replace them with '#include "newoff.h"'.
  200. **      Then run 'offsets tde.exe > newoff.h'.  Now re-compile tdecfg
  201. **      and you're done!
  202. **
  203. */
  204. /*****************************   end   *******************************/
  205.  
  206.  
  207. /*
  208.  * Name:    build_next_table
  209.  * Date:    August 29, 1993
  210.  * Notes:   the algorithm for building the next table is based the description
  211.  *           by KMP in _SIAM J Comp_, page 328.  Hints for a C implementation
  212.  *           are from Dr. Sedgewick's book, page 283.
  213.  */
  214. void build_next_table( char *pattern, char *next )
  215. {
  216. int  j;
  217. int  t;
  218. int  len;
  219.  
  220.    len = strlen( pattern );
  221.    t = next[0] = -1;
  222.    j = 0;
  223.    while (j < len) {
  224.       while (t >= 0  &&  pattern[j] != pattern[t])
  225.          t = (int)next[t];
  226.       j++;
  227.       t++;
  228.       next[j] =  pattern[j] == pattern[t]  ?  next[t]  :  (char)t;
  229.    }
  230. }
  231.  
  232.  
  233. /*
  234.  * Name:    find_offsets
  235.  * Date:    June 5, 1993
  236.  *          August 29, 1993
  237.  * Notes:   to increase the speed, we use a pattern matching machine
  238.  *           for each of the signatures.  on one pass through the file, all 7
  239.  *           signatures will be found.  it's also a little faster if we read
  240.  *           the file in big chunks.  also note that we never have to back-up
  241.  *           or reread the file.
  242.  *
  243.  *          this implementation is pretty much based on the description by
  244.  *           KMP in _SIAM J Comp_, page 326 (middle of the page.)  hints for
  245.  *           a C implementation are from Dr. Sedgewick's book, page 282, 285.
  246.  *
  247.  *   original KMP implementation by:  James H. Thompson, jimmy_t@verifone.com
  248.  */
  249. int  find_offsets( char *buff )
  250. {
  251. long off;
  252. int  m1, m2, m3, m4, m5, m6, m7;
  253. char sig1[8] = { '\x00','\x01','\x02','\x03','\x04','\x05','\x06','\x07' };
  254. char sig2[8] = "$ modes";
  255. char sig3[8] = "$colors";
  256. char sig4[8] = "$macbuf";
  257. char sig5[8] = "$  keys";
  258. char sig6[8] = "$twokey";
  259. char sig7[8] = "$  help";
  260. char sig1_next[8];
  261. char sig2_next[8];
  262. char sig3_next[8];
  263. char sig4_next[8];
  264. char sig5_next[8];
  265. char sig6_next[8];
  266. char sig7_next[8];
  267. unsigned int cnt;
  268. register char *b;
  269.  
  270.    /* build the _next[] tables */
  271.    build_next_table( sig1, sig1_next );
  272.    build_next_table( sig2, sig2_next );
  273.    build_next_table( sig3, sig3_next );
  274.    build_next_table( sig4, sig4_next );
  275.    build_next_table( sig5, sig5_next );
  276.    build_next_table( sig6, sig6_next );
  277.    build_next_table( sig7, sig7_next );
  278.  
  279.    /*
  280.     * Let's start the machines 100k into the executable.
  281.     */
  282.    m1 = m2 = m3 = m4 = m5 = m6 = m7 = 0;
  283.    off = 100000L;
  284.    sort_offset = mode_offset    = color_offset = macro_offset = 0L;
  285.    keys_offset = two_key_offset = help_offset  = 0L;
  286.    fseek( tde_exe, off, SEEK_SET );
  287.    while (!feof( tde_exe )) {
  288.       cnt = fread( buff, sizeof(char), 8192, tde_exe );
  289.       b = (char *)buff;
  290.       for (; cnt > 0; off++, cnt--, b++) {
  291.  
  292.          /*
  293.           * original KMP search implementation by: Jimmy Thompson
  294.           */
  295.          if (m1 < 8) {
  296.             if (sig1[m1] == *b) {
  297.                m1++;
  298.                if (m1 == 8)
  299.                   sort_offset = off - 7L;
  300.             } else {
  301.                while (m1 > 0  &&  *b != sig1[m1])
  302.                   m1 = (int)sig1_next[m1];
  303.                m1++;
  304.             }
  305.          }
  306.          if (m2 < 8) {
  307.             if (sig2[m2] == *b) {
  308.                m2++;
  309.                if (m2 == 8)
  310.                   mode_offset = off - 7L;
  311.             } else {
  312.                while (m2 > 0  &&  *b != sig2[m2])
  313.                   m2 = (int)sig2_next[m2];
  314.                m2++;
  315.             }
  316.          }
  317.          if (m3 < 8) {
  318.             if (sig3[m3] == *b) {
  319.                m3++;
  320.                if (m3 == 8)
  321.                   color_offset = off - 7L;
  322.             } else {
  323.                while (m3 > 0  &&  *b != sig3[m3])
  324.                   m3 = (int)sig3_next[m3];
  325.                m3++;
  326.             }
  327.          }
  328.          if (m4 < 8) {
  329.             if (sig4[m4] == *b) {
  330.                m4++;
  331.                if (m4 == 8)
  332.                   macro_offset = off - 7L;
  333.             } else {
  334.                while (m4 > 0  &&  *b != sig4[m4])
  335.                   m4 = (int)sig4_next[m4];
  336.                m4++;
  337.             }
  338.          }
  339.          if (m5 < 8) {
  340.             if (sig5[m5] == *b) {
  341.                m5++;
  342.                if (m5 == 8)
  343.                   keys_offset = off - 7L;
  344.             } else {
  345.                while (m5 > 0  &&  *b != sig5[m5])
  346.                   m5 = (int)sig5_next[m5];
  347.                m5++;
  348.             }
  349.          }
  350.          if (m6 < 8) {
  351.             if (sig6[m6] == *b) {
  352.                m6++;
  353.                if (m6 == 8)
  354.                   two_key_offset = off - 7L;
  355.             } else {
  356.                while (m6 > 0  &&  *b != sig6[m6])
  357.                   m6 = (int)sig6_next[m6];
  358.                m6++;
  359.             }
  360.          }
  361.          if (m7 < 8) {
  362.             if (sig7[m7] == *b) {
  363.                m7++;
  364.                if (m7 == 8)
  365.                   help_offset = off - 7L;
  366.             } else {
  367.                while (m7 > 0  &&  *b != sig7[m7])
  368.                   m7 = (int)sig7_next[m7];
  369.                m7++;
  370.             }
  371.          }
  372.       }
  373.    }
  374.    m1 = OK;
  375.    if (sort_offset  == 0L || mode_offset == 0L || color_offset   == 0L ||
  376.        macro_offset == 0L || keys_offset == 0L || two_key_offset == 0L ||
  377.        help_offset  == 0L)
  378.       m1 = ERROR;
  379.    return( m1 );
  380. }
  381.  
  382.  
  383. /*
  384.  * Name:    xygoto
  385.  * Date:    July 21, 1991
  386.  * Notes:   Use the video interrupt to set the cursor.
  387.  */
  388. void xygoto( int col, int row )
  389. {
  390. union REGS inregs, outregs;
  391.  
  392.    inregs.h.ah = 2;
  393.    inregs.h.bh = 0;
  394.    inregs.h.dh = row;
  395.    inregs.h.dl = col;
  396.    int86( VIDEO_INT, &inregs, &outregs );
  397. }
  398.  
  399.  
  400. /*
  401.  * Name:    video_config
  402.  * Date:    July 21, 1991
  403.  * Notes:   See main.c for more info.
  404.  */
  405. void video_config( void )
  406. {
  407. #pragma pack( 1 )    /* Use pragma to force packing on byte boundaries. */
  408.  
  409. struct LOWMEMVID
  410. {
  411.    char     vidmode;           /* 0x449 */
  412.    unsigned scrwid;            /* 0x44A */
  413.    unsigned scrlen;            /* 0x44C */
  414.    unsigned scroff;            /* 0x44E */
  415.    struct   LOCATE
  416.    {
  417.       unsigned char col;
  418.       unsigned char row;
  419.    } csrpos[8];                /* 0x450 */
  420.    struct   CURSIZE
  421.    {
  422.       unsigned char end;
  423.       unsigned char start;
  424.    } csrsize;                  /* 0x460 */
  425.    char      page;             /* 0x462 */
  426.    unsigned  addr_6845;        /* 0x463 */
  427.    char      crt_mode_set;     /* 0x465 */
  428.    char      crt_palette;      /* 0x466 */
  429.    char      system_stuff[29]; /* 0x467 */
  430.    char      rows;             /* 0x484 */
  431.    unsigned  points;           /* 0x485 */
  432.    char      ega_info;         /* 0x487 */
  433.    char      info_3;           /* 0x488 */
  434. } vid;
  435. struct LOWMEMVID _far *pvid = &vid;
  436.  
  437. #pragma pack( )    /* revert to previously defined pack pragma. */
  438.  
  439. union REGS in, out;
  440. unsigned char temp, active_display;
  441.  
  442.    /* Move system information into uninitialized structure variable. */
  443.    movedata( 0, 0x449, FP_SEG( pvid ), FP_OFF( pvid ), sizeof( vid ) );
  444.  
  445.    cfg.rescan = FALSE;
  446.    in.x.ax =  0x1a00;
  447.    int86( VIDEO_INT, &in, &out );
  448.    temp = out.h.al;
  449.    active_display = out.h.bl;
  450.    if (temp == 0x1a && (active_display == 7 || active_display == 8))
  451.       cfg.adapter = VGA;
  452.    else {
  453.       in.h.ah =  0x12;
  454.       in.h.bl =  0x10;
  455.       int86( VIDEO_INT, &in, &out );
  456.       if (out.h.bl != 0x10) {         /* EGA */
  457.          if (vid.ega_info & 0x08) {
  458.             if (vid.addr_6845 == 0x3d4)
  459.                cfg.adapter = CGA;
  460.             else
  461.                cfg.adapter = MDA;
  462.          } else
  463.             cfg.adapter = EGA;
  464.       } else if (vid.addr_6845 == 0x3d4)
  465.          cfg.adapter = CGA;
  466.       else
  467.          cfg.adapter = MDA;
  468.    }
  469.  
  470.    if (cfg.adapter == CGA)
  471.       cfg.rescan = TRUE;
  472.  
  473.    cfg.mode = vid.vidmode;
  474.    if (vid.addr_6845 == 0x3D4) {
  475.       cfg.color = TRUE;
  476.       FP_SEG( cfg.videomem ) = 0xb800;
  477.    } else {
  478.       cfg.color = FALSE;
  479.       FP_SEG( cfg.videomem ) = 0xb000;
  480.    }
  481.    FP_OFF( cfg.videomem ) = 0x0000;
  482.    if (cfg.color == TRUE)
  483.       cfg.attr = COLOR_ATTR;
  484.    else
  485.       cfg.attr = MONO_ATTR;
  486.  
  487.    cfg.overscan = vid.crt_palette;
  488. }
  489.  
  490.  
  491. /*
  492.  * Name:    getkey
  493.  * Date:    July 21, 1991
  494.  * Notes:   Waits for keyboard input and returns the key pressed by the user.
  495.  */
  496. int getkey( void )
  497. {
  498. unsigned key;
  499. unsigned lo;
  500.  
  501.    /*
  502.     *  _bios_keybrd == int 16.  It returns the scan code in ah, hi part of key,
  503.     *  and the ascii key code in al, lo part of key.
  504.     */
  505.    key = _bios_keybrd( 0 );
  506.    lo = key & 0X00FF;
  507.    lo = (int)((lo == 0) ? (((key & 0XFF00) >> 8) + 256) : lo);
  508.    return( lo );
  509. }
  510.  
  511.  
  512. /*
  513.  * Name:    s_output
  514.  * Date:    July 21, 1991
  515.  * Passed:  s:     the string to display
  516.  *          line:  line number to begin display
  517.  *          col:   column number to begin display
  518.  *          attr:  color to display string
  519.  * Notes:   See tdeasm.c for more info
  520.  */
  521. void s_output( char far *s, int line, int col, int attr )
  522. {
  523. int far *screen_ptr;
  524. int max_col;
  525. int off;
  526.  
  527.    max_col = 80;
  528.    screen_ptr = cfg.videomem;
  529.    off = line * 160 + col * 2;
  530.  
  531.    ASSEMBLE {
  532.         push    ds              /* MUST save ds */
  533.         push    di              /* save di on stack */
  534.         push    si              /* save si on stack */
  535.  
  536.         mov     bx, WORD PTR attr               /* keep attribute in bx */
  537.         mov     cx, WORD PTR col                /* put cols in cx */
  538.         mov     dx, WORD PTR max_col            /* keep max_col in dx */
  539.         mov     di, WORD PTR screen_ptr         /* load offset of screen ptr */
  540.         add     di, WORD PTR off
  541.         mov     ax, WORD PTR screen_ptr+2       /* load segment of screen ptr */
  542.         mov     es, ax
  543.         mov     si, WORD PTR s  /* load offset of string ptr */
  544.         or      si, si          /* is it == NULL? */
  545.         je      getout          /* yes, no output needed */
  546.         mov     ax, WORD PTR s+2        /* load segment of string ptr */
  547.         or      ax, ax          /* is pointer == NULL? */
  548.         je      getout          /* yes, no output needed */
  549.         mov     ds, ax          /* load segment of text in ds */
  550.         mov     ah, bl          /* put attribute in AH */
  551.    }
  552. top:
  553.  
  554.    ASSEMBLE {
  555.         cmp     cx, dx          /* col < max_cols? */
  556.         jge     getout          /* no, thru with line */
  557.         lodsb                   /* get next char in string - put in al */
  558.         or      al, al          /* is it '\0' */
  559.         je      getout          /* yes, end of string */
  560.         stosw                   /* else show attr + char on screen (ah + al) */
  561.         inc     cx              /* col++ */
  562.         jmp     SHORT top       /* get another character */
  563.    }
  564. getout:
  565.  
  566.    ASSEMBLE {
  567.         pop     si              /* get back si */
  568.         pop     di              /* get back di */
  569.         pop     ds              /* get back ds */
  570.    }
  571. }
  572.  
  573.  
  574. /*
  575.  * Name:    hlight_line
  576.  * Date:    July 21, 1991
  577.  * Passed:  x:     column to begin hi lite
  578.  *          y:     line to begin hi lite
  579.  *          lgth:  number of characters to hi lite
  580.  *          attr:  attribute color
  581.  * Notes:   The attribute byte is the hi byte.
  582.  */
  583. void hlight_line( int x, int y, int lgth, int attr )
  584. {
  585. int off, far *pointer;
  586.  
  587.    pointer = cfg.videomem;
  588.    off = y * 160 + 2 * x + 1;  /* add one - so it points to attribute byte */
  589.    ASSEMBLE {
  590.         push    di              /* save es */
  591.  
  592.         mov     cx, lgth        /* number of characters to change color */
  593.  
  594.         mov     di, WORD PTR pointer    /* get destination - video memory */
  595.         add     di, off                 /* add offset */
  596.         mov     ax, WORD PTR pointer+2
  597.         mov     es, ax
  598.         mov     ax, attr        /* attribute */
  599.    }
  600. lite_len:
  601.  
  602.    ASSEMBLE {
  603.         stosb                   /* store a BYTE */
  604.         inc     di              /* skip over character to next attribute */
  605.         loop    lite_len        /* change next attribute */
  606.         pop     di              /* restore di */
  607.    }
  608. }
  609.  
  610.  
  611. /*
  612.  * Name:    scroll_window
  613.  * Date:    October 5, 1991
  614.  * Passed:  lines:  number of lines to scroll
  615.  *          r1:     row scroll starts on
  616.  *          c1:     column scroll start on
  617.  *          r2:     ending row of scroll
  618.  *          c2:     ending column of scroll
  619.  *          attr:   color of scroll
  620.  * Notes:   Clear a window using color.  Use standard BIOS call.  See
  621.  *          any technical reference for more info on VIDEO BIOS services.
  622.  */
  623. void scroll_window( int lines, int r1, int c1, int r2, int c2, int attr )
  624. {
  625. char rah, ral;
  626.  
  627.    ASSEMBLE {
  628.         mov     ax, lines
  629.         cmp     ax, 0           /* if line < 0  - scroll window down */
  630.         jge     a1
  631.  
  632.         neg     ax                      /* make lines positive */
  633.         mov     BYTE PTR ral, al        /* save number of lines */
  634.         mov     BYTE PTR rah, 7         /* function 7 -  scroll window down */
  635.         dec     r2                      /* decrement row 2 */
  636.         jmp     SHORT a2
  637.    }
  638. a1:
  639.  
  640.    ASSEMBLE {
  641.         mov     BYTE PTR ral, al        /* number of lines to scroll */
  642.         mov     BYTE PTR rah, 6         /* function 6 - scroll window up */
  643.    }
  644. a2:
  645.  
  646.    ASSEMBLE {
  647.         mov     ax, WORD PTR r1         /* get starting row */
  648.         mov     ch, al                  /* put it in ch */
  649.         mov     ax, WORD PTR c1         /* get starting column */
  650.         mov     cl, al                  /* put it in cl */
  651.         mov     ax, WORD PTR r2         /* get ending row */
  652.         mov     dh, al                  /* put it in dh */
  653.         mov     ax, WORD PTR c2         /* get ending column */
  654.         mov     dl, al                  /* put it in cl */
  655.         mov     ax, WORD PTR attr       /* get attribute */
  656.         mov     bh, al                  /* put it in bh */
  657.         mov     ah, BYTE PTR rah        /* get function number */
  658.         mov     al, BYTE PTR ral        /* get number of lines */
  659.         push    bp                      /* ** in some early BIOS versions ** */
  660.         int     VIDEO_INT               /* ** u must save bp              ** */
  661.         pop     bp
  662.    }
  663. }
  664.  
  665.  
  666. /*
  667.  * Name:    cls
  668.  * Date:    October 5, 1991
  669.  * Notes:   Clear screen using color.
  670.  */
  671. void cls( void )
  672. {
  673.    scroll_window( 0, 0, 0, 24, 79, NORMAL );
  674. }
  675.  
  676.  
  677. /*
  678.  * Name:    show_box
  679.  * Date:    October 5, 1991
  680.  * Passed:  x:     number of lines to scroll
  681.  *          y:     row scroll starts on
  682.  *          p:     column scroll start on
  683.  *          attr:  ending row of scroll
  684.  * Notes:   Easy way to show text on screen.  Based on the display techiniques
  685.  *          in a very good morse code practice program, sorry I don't know
  686.  *          the author's name.  Several morse code pratice programs have been
  687.  *          written, but I am refering to the one written in C and released
  688.  *          around 1984-1986.  Seems like the author was living in California
  689.  *          at that time.
  690.  */
  691. void show_box( int x, int y, struct screen *p, int  attr )
  692. {
  693.  
  694.    while (p->text) {
  695.       s_output( p->text, p->row+y, p->col+x, attr );
  696.       p++;
  697.    }
  698. }
  699.  
  700.  
  701. /*
  702.  * Name:    make_window
  703.  * Date:    October 5, 1991
  704.  * Passed:  col:     upper left column to begin window
  705.  *          row:     upper left row to begin window
  706.  *          width:   number of columns in window
  707.  *          height:  number of rows in window
  708.  *          attr:    color of window border
  709.  * Notes:   Draw the outline of the window then clear all contents.
  710.  *          The begin and ending column have to incremented so when the
  711.  *          window is cleared the borders are not wiped out.
  712.  */
  713. void make_window( int col, int row, int width, int height, int attr )
  714. {
  715.    buf_box( col++, row++, width, height, attr );
  716.    clear_window( col, row, width-2, height-2 );
  717. }
  718.  
  719.  
  720. /*
  721.  * Name:    buf_box
  722.  * Date:    October 5, 1991
  723.  * Passed:  col:     upper left column to begin window
  724.  *          row:     upper left row to begin window
  725.  *          width:   number of columns in window
  726.  *          height:  number of rows in window
  727.  *          attr:    color of window border
  728.  * Notes:   Draw the outline of the window.  See tdecfg.h for the outline
  729.  *          characters.
  730.  */
  731. void buf_box( int col, int row, int width, int height, int attr )
  732. {
  733. int  i;
  734. int  row_count;
  735. char string[82];
  736.  
  737.    if (height > 0 && width > 0 && height < 25 && width < 81) {
  738.       row_count = 1;
  739.       string[0]= U_LEFT;
  740.       for (i=1; i<width-1; i++)
  741.          string[i] = HOR_LINE;
  742.       string[i++] = U_RIGHT; string[i] = '\0';
  743.       s_output( string, row, col, attr );
  744.       ++row_count;
  745.       ++row;
  746.  
  747.       if (row_count < height) {
  748.          string[0] = VER_LINE;
  749.          string[1] = '\0';
  750.          for (i=1; i<height-1; i++) {
  751.             s_output( string, row, col, attr );
  752.             s_output( string, row, col+width-1, attr );
  753.             ++row;
  754.             ++row_count;
  755.          }
  756.       }
  757.  
  758.       if (row_count <= height) {
  759.          string[0] = L_LEFT;
  760.          for (i=1; i<width-1; i++)
  761.             string[i] = HOR_LINE;
  762.          string[i++] = L_RIGHT; string[i] = '\0';
  763.          s_output( string, row, col, attr );
  764.       }
  765.    }
  766. }
  767.  
  768.  
  769. /*
  770.  * Name:    clear_window
  771.  * Date:    October 5, 1991
  772.  * Passed:  col:     upper left column to begin window
  773.  *          row:     upper left row to begin window
  774.  *          width:   number of columns in window
  775.  *          height:  number of rows in window
  776.  * Notes:   Clear the insides of the window.
  777.  */
  778. void clear_window( int col, int row, int width, int height )
  779. {
  780. /*   scroll_window( height, row, col, row+height-1, col+width-1, NORMAL ); */
  781.    scroll_window( 0, row, col, row+height-1, col+width-1, NORMAL );
  782. }
  783.  
  784.  
  785. /*
  786.  * Name:    window_control
  787.  * Date:    October 5, 1991
  788.  * Passed:  window_ptr: pointer to pointer of window (head of window stack)
  789.  *          action:     are SAVEing or RESTOREing the contents of a window
  790.  *          col:        upper left column of window
  791.  *          row:        upper left row of window
  792.  *          width:      number of characters in window
  793.  *          height:     number of rows in window
  794.  * Notes:   Save or restore the contents of the screen under a pop-up or
  795.  *          pull-down window.  Use a stack to store the windows so an unlimited
  796.  *          number of windows may be saved and restored.
  797.  */
  798. void window_control( WINDOW **window_ptr, int action, int col, int row,
  799.                      int width, int height )
  800. {
  801. WINDOW  *p;
  802. size_t  store_me;
  803.  
  804.    if (action == SAVE) {
  805.       p = (WINDOW *)malloc( sizeof(WINDOW) );
  806.       if (p != NULL) {
  807.          p->n = NULL;
  808.  
  809.          /*
  810.           * push a window on the stack
  811.           */
  812.          if (*window_ptr != NULL)
  813.             p->n = *window_ptr;
  814.          *window_ptr = p;
  815.          store_me = (width * height) * sizeof( int );
  816.          p->buf = (int *)malloc( store_me );
  817.          save_window( p->buf, col, row, width, height );
  818.       }
  819.    } else if (action == RESTORE) {
  820.       if (*window_ptr != NULL) {
  821.          p = *window_ptr;
  822.          restore_window( p->buf, col, row, width, height );
  823.  
  824.          /*
  825.           * pop a window off the stack
  826.           */
  827.          *window_ptr = p->n;
  828.          free( p->buf );
  829.          free( p );
  830. }  }  }
  831.  
  832.  
  833. /*
  834.  * Name:    save_window
  835.  * Date:    October 5, 1991
  836.  * Passed:  destination: pointer to store contents of screen
  837.  *          col:         upper left column of window
  838.  *          row:         upper left row of window
  839.  *          width:       number of characters in window
  840.  *          height:      number of rows in window
  841.  * Notes:   Do an optimal save.  Save only the contents of the screen that the
  842.  *          window writes over.  Some algorithms save the entire contents of
  843.  *          the screen - wasteful.
  844.  */
  845. void save_window( int *destination, int col, int row, int width, int height )
  846. {
  847. int i, j, offset;
  848. int far *pointer;
  849.  
  850.    pointer = cfg.videomem;
  851.    offset = row * 80 + col;
  852.    pointer += offset;
  853.    for (i=0; i < height; i++) {
  854.       for (j=0; j < width; j++)
  855.          *destination++ = *(pointer + j);
  856.       pointer += 80;
  857.    }
  858. }
  859.  
  860.  
  861. /*
  862.  * Name:    restore_window
  863.  * Date:    October 5, 1991
  864.  * Passed:  source:      pointer of source of contents of screen
  865.  *          col:         upper left column of window
  866.  *          row:         upper left row of window
  867.  *          width:       number of characters in window
  868.  *          height:      number of rows in window
  869.  * Notes:   Do an optimal restore.  Restore only the contents of the screen
  870.  *          that the window writes over.  Some algorithms restore the entire
  871.  *          contents of the screen - wasteful.
  872.  */
  873. void restore_window( int *source, int col, int row, int width, int height )
  874. {
  875. int i, j, offset;
  876. int far *pointer;
  877.  
  878.    pointer = cfg.videomem;
  879.    offset = row * 80 + col;
  880.    pointer += offset;
  881.    for (i=0; i < height; i++) {
  882.       for (j=0; j < width; j++)
  883.          *(pointer + j) = *source++;
  884.       pointer += 80;
  885.    }
  886. }
  887.